"""Base analyzer interface for language-agnostic analysis."""

from __future__ import annotations

import json
from abc import ABC, abstractmethod
from dataclasses import dataclass, asdict
from pathlib import Path
from typing import Dict, List, Optional, Any, Set


@dataclass
class FunctionInfo:
    """Unified function information across languages."""
    name: str
    full_name: str
    namespace: str = ""
    class_name: Optional[str] = None
    return_type: str = ""
    parameters: List[str] = None
    line_count: int = 0
    source_file: str = ""
    start_line: int = 0
    end_line: int = 0
    language: str = ""

    def __post_init__(self):
        if self.parameters is None:
            self.parameters = []

    def to_dict(self) -> Dict[str, Any]:
        """Convert to dictionary for JSON serialization."""
        return asdict(self)


@dataclass
class CallGraph:
    """Unified call graph representation."""
    edges: Dict[str, Set[str]] = None

    def __post_init__(self):
        if self.edges is None:
            self.edges = {}

    def add_call(self, caller: str, callee: str):
        """Add a call relationship."""
        if caller not in self.edges:
            self.edges[caller] = set()
        self.edges[caller].add(callee)

    def get_callees(self, caller: str) -> Set[str]:
        """Get functions called by the given function."""
        return self.edges.get(caller, set())

    def get_callers(self, callee: str) -> Set[str]:
        """Get functions that call the given function."""
        callers = set()
        for caller, callees in self.edges.items():
            if callee in callees:
                callers.add(caller)
        return callers

    def to_dict(self) -> Dict[str, Any]:
        """Convert to dictionary for JSON serialization."""
        return {
            "edges": {caller: list(callees) for caller, callees in self.edges.items()}
        }


@dataclass
class AnalysisResult:
    """Unified analysis result."""
    functions: List[FunctionInfo]
    call_graph: CallGraph
    cycles: List[List[str]] = None
    statistics: Dict[str, Any] = None
    language: str = ""

    def __post_init__(self):
        if self.cycles is None:
            self.cycles = []
        if self.statistics is None:
            self.statistics = {}

    def to_dict(self) -> Dict[str, Any]:
        """Convert to dictionary for JSON serialization."""
        return {
            "functions": [f.to_dict() for f in self.functions],
            "call_graph": self.call_graph.to_dict(),
            "cycles": self.cycles,
            "statistics": self.statistics,
            "language": self.language
        }

    def save_json(self, path: Path) -> None:
        """Save analysis result to JSON file."""
        with open(path, 'w') as f:
            json.dump(self.to_dict(), f, indent=2)


class LanguageAnalyzer(ABC):
    """Abstract base class for language analyzers."""

    @abstractmethod
    def analyze(self, paths: List[Path], **kwargs) -> AnalysisResult:
        """Analyze source files and return unified result."""
        pass

    @abstractmethod
    def get_supported_extensions(self) -> List[str]:
        """Return list of supported file extensions."""
        pass

    @abstractmethod
    def get_language_name(self) -> str:
        """Return the language name."""
        pass